#include "mapwidget.h"
#include "ui_mapwidget.h"
#include <QPen>
#include <QApplication>
#define MAP_SIZE 2000
/*
地图显示类
*/

MapWidget::MapWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MapWidget)
{
    ui->setupUi(this);
    car = new Car(ui->map ,ui->map);
    pathPos = new QCPCurve(ui->map->xAxis, ui->map->yAxis);
    nextIndex = 0;
    global_view = true;
    needFindeStation = true;
    basePath = qApp->applicationDirPath();
    creatGraphs();
//    readPathPoint(getPathFileName());//读取路线坐标
//    readStationPoint(getStationFileName());//读取站点坐标
}

MapWidget::~MapWidget()
{
    delete ui;
}

void MapWidget::creatGraphs()
{
    QPen drawPen;
    drawPen.setColor(Qt::white);
    drawPen.setWidth(4);

    QCPGraph *graph = ui->map->addGraph();//普通坐标
    graph->setSelectable(QCP::stMultipleDataRanges);
    graph->setPen(drawPen);
    graph->setLineStyle(QCPGraph::lsNone);
    graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 2));
    graphs<<graph;

    drawPen.setColor(Qt::green);
    QCPGraph *graph_light = ui->map->addGraph();//红绿灯坐标
    graph_light->setSelectable(QCP::stMultipleDataRanges);
    graph_light->setPen(drawPen);
    graph_light->setLineStyle(QCPGraph::lsNone);
    graph_light->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 8));
    graphs<<graph_light;

//    drawPen.setColor(Qt::yellow);
//    QCPGraph *graph_light_over = ui->map->addGraph();//红绿灯结束
//    graph_light_over->setSelectable(QCP::stMultipleDataRanges);
//    graph_light_over->setPen(drawPen);
//    graph_light_over->setLineStyle(QCPGraph::lsNone);
//    graph_light_over->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 8));
//    graphs<<graph_light_over;

    drawPen.setColor(Qt::red);
    QCPGraph *graph_sidewalk = ui->map->addGraph();//人行道坐标
    graph_sidewalk->setSelectable(QCP::stMultipleDataRanges);
    graph_sidewalk->setPen(drawPen);
    graph_sidewalk->setLineStyle(QCPGraph::lsNone);
    graph_sidewalk->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 8));
    graphs<<graph_sidewalk;

    drawPen.setColor(Qt::blue);
    QCPGraph *graph_curve = ui->map->addGraph();//转弯减速坐标
    graph_curve->setSelectable(QCP::stMultipleDataRanges);
    graph_curve->setPen(drawPen);
    graph_curve->setLineStyle(QCPGraph::lsNone);
    graph_curve->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 8));
    graphs<<graph_curve;

    drawPen.setColor(Qt::gray);
    QCPGraph *graph_station = ui->map->addGraph();//站点
    graph_station->setSelectable(QCP::stMultipleDataRanges);
    graph_station->setPen(drawPen);
    graph_station->setLineStyle(QCPGraph::lsNone);
    graph_station->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 8));
    graphs<<graph_station;
}

void MapWidget::addGraphData(double x, double y, int index)
{
    graphs.at(index)->addData(x, y);
}

void MapWidget::graphsDataClear()
{
    ui->map->clearGraphs();
    creatGraphs();
}

void MapWidget::readPathPoint(QString fileName)
{
    qDebug()<<"readPathPoint"<<fileName;
    if(fileName.isEmpty())
        return;

    QFile f(fileName);
    f.open(QFile::ReadOnly);

    QPointF p;
    QByteArray qba;
    if(!list_path.isEmpty())
    {
        list_path.clear();
        list_path.squeeze();
    }
    int i=0;
    while(!(qba = f.readLine()).isEmpty())
    {
        QString str = QString(qba);
//        qDebug()<<"[readPoint]"<<str;
        QStringList l = str.split(" ", QString::SkipEmptyParts);
        if(l.count() < 2)
        {
            qDebug()<<"[readPoint]:File fomat error.";
            return;
        }
        bool ok;

        p.setX(l.at(0).toDouble(&ok));
        if(!ok)
        {
            qDebug()<<"[readPoint]:File fomat error.";
            return;
        }
        p.setY(l.at(1).toDouble(&ok));
        if(!ok)
        {
            qDebug()<<"[readPoint]:File fomat error.";
            return;
        }
//        if(i%5 == 0)
        list_path.push_back(p);
        i++;
    }
//    list_path.push_back(p);
    f.close();

//    BSpline b_spline;
//    QVector<QPointF> pathPoints = b_spline.generateCurve(list_path, 3, 0.2);
//    QVector<QCPCurveData> curData(pathPoints.count());

    QVector<QPointF> pathPoints = list_path;
    QVector<QCPCurveData> curData(list_path.count());

//    fileName = fileName+".bs";
//    QFile nf(fileName);
//    nf.open(QFile::WriteOnly);
//    foreach(p, pathPoints)
//    {
//        nf.write((QString("%1 %2\n").arg(p.x()).arg(p.y())).toLocal8Bit());
//    }
//    nf.close();


    for(int i=0; i<pathPoints.count(); i++)
    {
        qDebug()<<(double)pathPoints.at(i).x()<<pathPoints.at(i).y();
        curData[i] = QCPCurveData(i, pathPoints.at(i).x(), pathPoints.at(i).y());
    }

//    QVector<QCPCurveData> oriData(list_path.count());
//    for(int i=0; i<list_path.count(); i++)
//    {
//        oriData[i] = QCPCurveData(i, list_path.at(i).x(), list_path.at(i).y());
//    }
//    QCPCurve* oriPathPos = new QCPCurve(ui->map->xAxis, ui->map->yAxis);
//    oriPathPos->data()->set(oriData,true);
//    oriPathPos->setPen(QPen(QBrush(QColor(150,50,50)), 1));

    pathPos->data()->set(curData, true);
    pathPos->setPen(QPen(QBrush(QColor(50,150,50)), 10));
//    pathPos->setScatterStyle(QCPScatterStyle::ssCircle);
    pathPos->setScatterSkip(100);
    QPainterPath customScatterPath;
//    for (int i=0; i<3; ++i)
    i=0;
        customScatterPath.cubicTo(qCos(2*M_PI*i/3.0)*9, qSin(2*M_PI*i/3.0)*9, qCos(2*M_PI*(i+0.9)/3.0)*9, qSin(2*M_PI*(i+0.9)/3.0)*9, 0, 0);
    pathPos->setScatterStyle(QCPScatterStyle(customScatterPath, QPen(Qt::black, 0), QColor(40, 70, 255, 50), 10));

    ui->map->xAxis->setVisible(false);
    ui->map->yAxis->setVisible(false);
    ui->map->setInteractions(QCP::iRangeZoom | QCP::iSelectPlottables);
//QCP::iRangeDrag |
//    ui->map->setInteractions(QCP::iSelectPlottables);
//    ui->map->axisRect()->setupFullAxesBox();

    bool ok;
    QCPRange x_range = pathPos->getKeyRange(ok);
    if(!ok)
        return;
    QCPRange y_range = pathPos->getValueRange(ok);
    if(!ok)
        return;

    ui->map->rescaleAxes();

//缩放部分边框出来
    double x_size = x_range.size();
    x_range.lower -= x_size/20;
    x_range.upper += x_size/20;
    ui->map->xAxis->setRange(x_range);

    double y_size = y_range.size();
    y_range.lower -= y_size/20;
    y_range.upper += y_size/20;
    ui->map->yAxis->setRange(y_range);

    if(x_range.size()>y_range.size())
        ui->map->yAxis->scaleRange(x_range.size()/y_range.size());
    else
        ui->map->xAxis->scaleRange(y_range.size()/x_range.size());

//    ui->map->yAxis->setScaleRatio(ui->map->xAxis,1);

    car->setPos(list_path[0], 0);
    ui->map->replot();
}

void MapWidget::readStationPoint(QString fileName)
{
    if(fileName.isEmpty())
        return;
    QFile f(fileName);
    f.open(QFile::ReadOnly);

    QByteArray qba;
    QList<QPointF> list_point;
//    int i=0;

    clearStations();

    while(!(qba = f.readLine()).isEmpty())
    {
        QString str = QString(qba);
//        qDebug()<<"[readStationPoint]"<<str;
        QStringList l = str.split(" ", QString::SkipEmptyParts);
        if(l.count() != 3)
        {
            qDebug()<<"[readStationPoint]:File fomat error.";
            return;
        }
        bool ok;
        QPointF p;
        p.setX(l.at(0).toDouble(&ok));
        if(!ok)
        {
            qDebug()<<"[readStationPoint]:File fomat error.";
            return;
        }
        p.setY(l.at(1).toDouble(&ok));
        if(!ok)
        {
            qDebug()<<"[readStationPoint]:File fomat error.";
            return;
        }

        list_point<<p;
        StationPoint* stPoint = new StationPoint(list_point.count()-1,l.at(2),p, ui->map, ui->map);
        stPoint->setIndex(findPointIndex(p));
        list_station<<stPoint;
        stPoint->setAutoExclusive(true);
//        group_station.addButton(stPoint, i++);
        connect(stPoint, SIGNAL(gotoPos(QPointF, int)), this, SIGNAL(gotoPos(QPointF,int)));
    }
    f.close();
    car->raise();

//    for(int i=0; i<list_point.count(); i++)
//    {
//        StationPoint* stPoint = new StationPoint(list_point.at(i), ui->map, ui->map);
//        list_station<<stPoint;
//        group_station.addButton(stPoint, i);
//        connect(stPoint, SIGNAL(gotoPos(QPointF)), this, SIGNAL(gotoPos(QPointF)));
//    }
//    group_station.setExclusive(true);
}

void MapWidget::clearStations()
{
    if(!list_station.isEmpty())
    {
        qDeleteAll(list_station.begin(), list_station.end());
        list_station.clear();
    }
    QList<QAbstractButton *>lists = group_station.buttons();
    if(!lists.isEmpty())
    {
        for(int i=0; i<lists.count(); i++)
            group_station.removeButton(lists.at(i));
    }
}

void MapWidget::checkStation(QPointF p)
{
    if(list_station.isEmpty())
        return;
    qreal manVal = (p - list_station[nextIndex]->getPos()).manhattanLength();

    if(manVal < 0.1)
    {
        list_station[nextIndex]->setState(true);
        nextIndex++;
    }
    if(nextIndex>=list_station.count())
    {
        initStationState();
        nextIndex = 0;
    }
}

void MapWidget::initStationState()
{
    for(int i=0; i<list_station.count(); i++)
    {
        list_station[i]->setState(false);
    }
}

void MapWidget::findStation(QPointF p)
{
    int index = findPointIndex(p);
    StationPoint* station;
    nextIndex = 0;
    foreach(station, list_station)
    {
        if(station->mapIndex() < index)
        {
            station->setState(true);//station passed
            nextIndex++;
        }
        else
            return;
    }
}

void MapWidget::mapUpdate()
{

}

void MapWidget::mapRescale(bool isGlobalView)
{
    if(isGlobalView)
    {
        bool ok;
        QCPRange x_range = pathPos->getKeyRange(ok);
        if(!ok)
            return;
        QCPRange y_range = pathPos->getValueRange(ok);
        if(!ok)
            return;

        ui->map->rescaleAxes();

    //缩放部分边框出来
        double x_size = x_range.size();
        x_range.lower -= x_size/20;
        x_range.upper += x_size/20;
        ui->map->xAxis->setRange(x_range);

        double y_size = y_range.size();
        y_range.lower -= y_size/20;
        y_range.upper += y_size/20;
        ui->map->yAxis->setRange(y_range);

        if(x_range.size()>y_range.size())
            ui->map->yAxis->scaleRange(x_range.size()/y_range.size());
        else
            ui->map->xAxis->scaleRange(y_range.size()/x_range.size());

        ui->map->replot();
    }
    else
    {
        QPointF carPos = car->getPos();
        qreal viewSize = CAR_VIEW_SIZE;
        QCPRange y_range = QCPRange(carPos.y()-viewSize/2, carPos.y()+viewSize/2);
        viewSize *= ui->map->geometry().width()/ui->map->geometry().height();
        QCPRange x_range = QCPRange(carPos.x()-viewSize/2, carPos.x()+viewSize/2);
        ui->map->xAxis->setRange(x_range);
        ui->map->yAxis->setRange(y_range);
        ui->map->replot();
        qDebug()<<"[mapUpdate]"<<x_range<<y_range;
    }
}

int MapWidget::findPointIndex(QPointF p)
{
    qreal disMin = (p-list_path[0]).manhattanLength();
    QPointF vector;
    int index = 0;

    for(int i=0; i<list_path.count(); i++)
    {
        vector = p - list_path[i];
        qreal manVal = vector.manhattanLength();
        if(manVal == 0)
        {
            qDebug()<<"[findPointIndex] 0";
            return i;
        }
        if(manVal < disMin)
        {
            disMin = manVal;
            index = i;
        }
    }
    return index;
}

QString MapWidget::getPathFileName()
{
    QSettings settings(basePath+"/xingyun.conf", QSettings::IniFormat);
    return settings.value("MapPath", QString()).toString();
}

QString MapWidget::getStationFileName()
{
    QSettings settings(basePath+"/xingyun.conf", QSettings::IniFormat);
    return settings.value("StationPath",QString()).toString();
}

void MapWidget::setGlobalView(bool isGlobalView)
{
    global_view = isGlobalView;
    if(global_view)
    {
        car->setPos();
        car->setCarView(false);
        mapRescale(true);
//        checkStation(pos);
    }
    else
    {
        car->setPixPos(this->geometry().center());
        car->setCarView(true);
        mapRescale(false);
    }
}

void MapWidget::recvCarPos(QPointF pos, int ang)
{
    if(needFindeStation)
    {
        findStation(pos);
        needFindeStation = false;
    }
    if(global_view)
    {
        car->setPos(pos, ang);
        checkStation(pos);
    }
    else
    {
        car->updatePos(pos);
        car->setAngle(ang);
//        car->setPixPos(this->geometry().center(), ang);
        mapRescale(false);
    }
}

void MapWidget::updatePath()
{
    readPathPoint(getPathFileName());
}

void MapWidget::updateStation()
{
    readStationPoint(getStationFileName());
}

void MapWidget::newPos(double x, double y, QString yaw, QString , QString , QString , int posType)
{
    mapData.push_back(QCPCurveData(mapData.count(), x, y));

//    QVector<QCPCurveData> oriData(list_path.count());
//    for(int i=0; i<list_path.count(); i++)
//    {
//        oriData[i] = QCPCurveData(i, list_path.at(i).x(), list_path.at(i).y());
//    }
//    QCPCurve* oriPathPos = new QCPCurve(ui->map->xAxis, ui->map->yAxis);
//    oriPathPos->data()->set(oriData,true);
//    oriPathPos->setPen(QPen(QBrush(QColor(150,50,50)), 1));

    pathPos->data()->set(mapData, true);
    pathPos->setPen(QPen(QBrush(QColor(50,150,50)), 10));
//    pathPos->setScatterStyle(QCPScatterStyle::ssCircle);
//    pathPos->setScatterSkip(100);
    addGraphData(x, y, posType);

    ui->map->xAxis->setVisible(false);
    ui->map->yAxis->setVisible(false);
    ui->map->setInteractions(QCP::iRangeZoom | QCP::iSelectPlottables);
//QCP::iRangeDrag |
//    ui->map->setInteractions(QCP::iSelectPlottables);
//    ui->map->axisRect()->setupFullAxesBox();

    bool ok;
    QCPRange x_range = pathPos->getKeyRange(ok);
    if(!ok)
        return;
    QCPRange y_range = pathPos->getValueRange(ok);
    if(!ok)
        return;

    ui->map->rescaleAxes();

//缩放部分边框出来
    double x_size = x_range.size();
    x_range.lower -= x_size/20;
    x_range.upper += x_size/20;
    ui->map->xAxis->setRange(x_range);

    double y_size = y_range.size();
    y_range.lower -= y_size/20;
    y_range.upper += y_size/20;
    ui->map->yAxis->setRange(y_range);

    if(x_range.size()>y_range.size())
        ui->map->yAxis->scaleRange(x_range.size()/y_range.size());
    else
        ui->map->xAxis->scaleRange(y_range.size()/x_range.size());

//    ui->map->yAxis->setScaleRatio(ui->map->xAxis,1);

    car->setPos(QPointF(x,y), (int)yaw.toDouble());
    ui->map->replot();
}

void MapWidget::drawMap()
{

}
